/*****************************************************


This is a template of a stand along program that is not
part of SLUG but it is useful to run large grid in which 
only some pramateres are modified continuosly. 
It also uses openmp to use multiple shared memory cores.


compile like this:

g++ -Wall -O3 grid_slug.cpp -o grid_slug -fopenmp


To limit the number of proceses that are executed at the same time 
use

export OMP_NUM_THREADS N_cpu

*******************************************************/

//load a bunch of libraries 
#include <sstream>
#include <iostream> 
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <vector>
#include <numeric>
#include <iterator>
#include <cctype>
#include <algorithm>

//enable parallel computing
#include<omp.h>

using namespace std;


/***************************************************
This is the function that writes part of the slug par file
that needs to be modifed
***************************************************/
void write_parfile(double thispar, string thisname, string current_parfile){

  //open file
  ofstream fp_out;
  fp_out.open(current_parfile.data(), ios::out);
  
  fp_out  << "timestep\t\t 8E7 #"<<endl;
  fp_out  << "maxtime \t\t 8E8 #"<<endl;
  fp_out  << "galaxy_sfr\t\t"<<thispar<<" #"<<endl;
  fp_out  << "imf_type\t\t SALPETER #"<<endl;
  fp_out  << "model_name\t\t"<<thisname<<" #"<<endl;
  fp_out  << "max_cluster_mass\t\t 1E7 #"<<endl;

  //end
  fp_out.close(); 
  
  return;
}


/***************************************************

This is the main. Nothing fancy, just a parrall for
loop that reads a file with the par to use 
and calls a function that write the par file and 
calls slug 

***************************************************/

int main(){


  //Here you read the file with the par that changes in the grid.
  //The first line should be the number of models
  string input_file("sfr_grid_test.txt");
  
  //Here set the root name of the model. Numbers are appendend to this
  string root_name("TEST_GRID");
  
  
  //make par folder
  system("mkdir -p par");
    
  //parse the input file here
  //read the halo file
  FILE *infile=fopen(input_file.data(),"r");
  if(infile==NULL){
    cout<<"Error in reading input file.."<<endl;
    exit(1);
  }
     
  //get number of models
  long numodel;
  double buff;
  fscanf(infile,"%ld",&numodel);
  
  //allocate space for parameter
  double *parvar = (double*) malloc(numodel*sizeof(double));
  
  //get the par
  for(int i=0;i<numodel;i++){
    fscanf(infile,"%lf",&buff);
    parvar[i]=buff;
  }
  
  fclose(infile);
  
  //now start a parallel loop to call slug
  long thismodel=0;
  string current_model_name,current_parfile,runthis;
  double current_par;
  
#pragma omp parallel for default(shared)			        \
  private(current_model_name,current_par,current_parfile,runthis)	\
  shared(thismodel,parvar)
  for(long mm=0;mm<numodel;mm++){
    
    //one at the time get their model name and value 
    //for the par
#pragma omp critical
    {
      //assign values
      current_par=parvar[thismodel];
      current_model_name.assign(root_name);
      
      //make file name and par name
      current_model_name.append("_");
      stringstream buff;
      buff<<thismodel+1;
      current_model_name.append(buff.str());
      current_parfile.assign("./par/");
      current_parfile.append(current_model_name);
      current_parfile.append(".param");
      
      cout<<"Running "<<thismodel+1<<" of "<<numodel<<" : "<<current_model_name<<endl;
      
      //increment models
      thismodel=thismodel+1;
    }
    
    //make the par file
    write_parfile(current_par,current_model_name,current_parfile);
    
    //spawn slug
    runthis.assign("$SLUG_DIR/slug ");
    runthis.append(current_parfile);
    system(runthis.data());
    
  }
  
  //free mem
  free(parvar);
  
  exit(0);
}
